﻿// ***********************************************************************
// Assembly         : TCPServerSocket
// Author           : yubao
// Created          : 07-18-2014
//
// Last Modified By : yubao
// Last Modified On : 07-30-2014
// ***********************************************************************
// <copyright file="ClientHandler.cs" company="www.cnblogs.com/dotcpp">
//     Copyright (c) www.cnblogs.com/dotcpp. All rights reserved.
// </copyright>
// <summary>客户端类，用于处理数据接收等</summary>
// ***********************************************************************


using System;
using System.Diagnostics;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Text;

namespace TCPServerSocket
{
    public class ClientHandler
    {
        public bool Alive { get; set; }
        public IPEndPoint IpEndPoint { get; private set; }

        private readonly TcpClient _clientSocket;
        private readonly NetworkStream _networkStream;
        private readonly byte[] _bytes;
        private int _bytesRead;

        public ClientHandler(TcpClient clientSocket)
        {
            _clientSocket = clientSocket;
            _networkStream = clientSocket.GetStream();
            _networkStream.ReadTimeout = 10;
            IpEndPoint = clientSocket.Client.RemoteEndPoint as IPEndPoint;
            _bytes = new byte[1000];
            Alive = true;
        }
        public void Process(Action<string, byte[], int> recvDataAction)
        {
            try
            {
                if (!_clientSocket.Connected || (!IsConnected))
                {
                    Close();
                    return;
                }
               
                _bytesRead = _networkStream.Read(_bytes, 0, (int)_bytes.Length);
               
                if (_bytesRead > 0)
                {
                    ProcessData(recvDataAction);
                }
                else  //当等于0的时候，竟然是SOCKET结束了？
                {
                    // All the data has arrived; put it in response.
                    ProcessData(recvDataAction);
                    Close();
                }
            }
            catch (SocketException exception)
            {
                Close();
            }
            catch (IOException exception)
            {
                // All the data has arrived; put it in response.
                ProcessData(recvDataAction);
            }

        }

        private void ProcessData(Action<string, byte[], int> recvDataAction)
        {
            if (_bytesRead > 0 && recvDataAction != null)
            {
                recvDataAction(ToString(), _bytes, _bytesRead);
                _bytesRead = 0;
            }
        }

        public void Close()
        {
            _networkStream.Close();
            _clientSocket.Close();
            Alive = false;
        }

        public void SendMessage(byte[] buffer)
        {
            if (!Alive) return;
            try
            {
                _networkStream.Write(buffer, 0, buffer.Length);
            }
            catch (Exception e)
            {
                Close();
            }
        }

        public override string ToString()
        {
            return IpEndPoint.Address.ToString();
        }

        public bool IsConnected
        {
            get
            {
                try
                {
                    return !(_clientSocket.Client.Poll(1, SelectMode.SelectRead) 
                        && _clientSocket.Available == 0);
                }
                catch(SocketException e)
                {
                    return false;
                }
            }
        }
    }
}
